import numpy as np
import cv2

def calibrate_eye_position(event_list, img_shape=(240, 346)):
    """
    眼睛位置偏移校准。将事件图像中心对齐到视野中心。
    参数:
        event_list: 包含4000个事件的一维列表 [p1, r1, c1, t1, ...]
        img_shape: 图像尺寸 (H, W)
    返回:
        offset_x, offset_y: 需要应用到后续事件的坐标偏移量
    """
    # 1. 累积事件生成灰度图
    pos_img = np.zeros(img_shape, dtype=np.int32)
    neg_img = np.zeros(img_shape, dtype=np.int32)
    num_events = len(event_list) // 4
    for j in range(num_events):
        p = event_list[j*4]
        r = event_list[j*4+1]
        c = event_list[j*4+2]
        if 0 <= r < img_shape[0] and 0 <= c < img_shape[1]:
            if p == 1:
                pos_img[r, c] += 1
            else:
                neg_img[r, c] += 1
    gray_img = pos_img + neg_img

    # 2. 中值滤波去噪
    gray_img = cv2.medianBlur(gray_img.astype(np.uint8), 5)

    # 3. 形态学操作（膨胀+腐蚀）
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (13, 13))
    morph_img = cv2.dilate(gray_img, kernel, iterations=2)
    morph_img = cv2.erode(morph_img, kernel, iterations=2)

    # 4. 二值化
    _, binary_img = cv2.threshold(morph_img, 1, 255, cv2.THRESH_BINARY)

    # 5. 找最大连通区域并计算外接矩形
    num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(binary_img)
    if num_labels <= 1:
        # 没有检测到眼睛区域，返回0偏移
        return 0, 0
    # stats[1:] 排除背景
    max_idx = np.argmax(stats[1:, cv2.CC_STAT_AREA]) + 1
    x, y, w, h, area = stats[max_idx]
    bbox_center_x = x + w // 2
    bbox_center_y = y + h // 2

    # 6. 计算偏移量
    image_center_x = img_shape[1] // 2
    image_center_y = img_shape[0] // 2
    offset_x = image_center_x - bbox_center_x
    offset_y = image_center_y - bbox_center_y

    return offset_x, offset_y

def apply_offset_to_events(event_list, offset_x, offset_y, img_shape=(240, 346)):
    """
    对事件流应用坐标偏移，超出边界的事件将被丢弃
    参数:
        event_list: 一维事件流列表 [p1, r1, c1, t1, ...]
        offset_x, offset_y: 坐标偏移量
        img_shape: 图像尺寸 (H, W)
    返回:
        new_event_list: 偏移后的事件流
    """
    new_event_list = []
    num_events = len(event_list) // 4
    for j in range(num_events):
        p = event_list[j*4]
        r = event_list[j*4+1] + offset_y
        c = event_list[j*4+2] + offset_x
        t = event_list[j*4+3]
        if 0 <= r < img_shape[0] and 0 <= c < img_shape[1]:
            new_event_list.extend([p, r, c, t])
    return new_event_list